# -*- coding:utf-8 -*-
import uuid
import datetime
import time
import redis
import re
import os
import sys
root_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(root_path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ElevatorAdmin.settings")
import django
django.setup()
from manufacturer.models import AuthorityCode, StatusMsg, AlarmMsg, ElevatorStatus, ElevatorFault
from utils.logger import get_logger
import random
from manufacturer.call_interface import elevator_status, elevator_alarm, elevator_register, device_status
import json

logger = get_logger("dev-register")


def register(device_type, manufacturer, device_sn, sim_no):
    logger.info("register ---------is-----coming------")
    logger.info(manufacturer)
    if manufacturer != "0208090702000000":
        return None, None
    if not sim_no or len(sim_no) != 12 or not sim_no.startswith("8888"):
        logger.info("sim 卡错误")
        logger.info(sim_no)
        return None, None
    logger.info("device_type")
    logger.info(device_type)
    if device_type.endswith("01"):
        c = "01"
    elif device_type.endswith("02"):
        c = "02"
    elif device_type.endswith("03"):
        c = "03"
    else:
        return None, None
    i = 1
    while True:
        logger.info("随机次数i: %s" % i)
        s = get_random_str()
        authority_code = AuthorityCode.objects.filter_active(code=s)
        if not authority_code:
            break
        i += 1
    base_str = sim_no[4:]
    collection_num = "HCCJ05" + base_str
    device_code_elevator = "28972" + base_str
    obj = AuthorityCode.objects.filter_active(sim_no=sim_no).first()
    if obj:
        created = False
        obj.device_type = c
        obj.manufacturer_code = manufacturer
        obj.device_code = device_sn
        obj.collection_num = collection_num
        obj.device_code_elevator = device_code_elevator
        if not obj.code:
            obj.code = s
            created = True
        obj.save()
    else:
        obj = AuthorityCode.objects.create(**{"code": s, "device_type": c, "sim_no": sim_no,
                                              "manufacturer_code": manufacturer, "device_code": device_sn,
                                              "collection_num": collection_num, "device_code_elevator": device_code_elevator
                                              })
        created = True

    # obj, created = AuthorityCode.objects.get_or_create(sim_no=sim_no, defaults={"code": s, "device_type": c,
    #                                                    "manufacturer_code": manufacturer, "device_code": device_sn,
    #                                                     "collection_num": collection_num, "device_code_elevator": device_code_elevator
    #                                                     })
    elevator_register.delay(obj.id)
    if created:
        r = redis.Redis(host="localhost", port=6379, db=2)
        r.sadd("code", obj.code)
        r.set(sim_no, obj.code)
        return obj.code, True
    else:
        return obj.code, False


def get_random_str(n=16):
    strs = ['"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
            'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
            'v', 'w', 'x', 'y', 'z', '{', '|']
    l = random.sample(strs, n)
    random.shuffle(l)
    ret = ''
    for c in l:
        ret += '%02x' % ord(c)
    return ret


def login(authority_code):
    obj = AuthorityCode.objects.filter_active(code=authority_code).first()
    if obj:
        obj.is_online = True
        obj.login_time = int(time.time())
        obj.save()
        try:
            device_status.delay(obj.code, datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
        except:
            pass
        return True
    else:
        return False


def get_authority_code(sim_no):
    r = redis.Redis(host="localhost", port=6379, db=2)
    authority_code = r.get(sim_no)
    if authority_code:
        login(authority_code)
    return authority_code


def logout(authority_code):
    obj = AuthorityCode.objects.filter_active(code=authority_code).first()
    if obj:
        obj.is_online = False
        obj.save()
        try:
            device_status.delay(obj.code, datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
        except:
            pass


def get_now():
    now = datetime.datetime.now().strftime("%S%M%H%d%m%Y")
    now = now[:10] + now[12:]
    return now


def get_today():
    now = datetime.datetime.today()
    today = datetime.datetime(year=now.year, month=now.month, day=now.day)
    return today


def create_elevator_status(obj):
    o = obj.authority_code.device_code_elevator
    f = obj.authority_code.manufacturer_code_elevator
    e = obj.authority_code.elevator_code
    u = str(obj.is_up) if obj.is_up in (0, 1) else None
    d = str(obj.is_down) if obj.is_down in (0, 1) else None
    if obj.is_stopped:
        lm = "0"
    elif obj.is_overhauling == 1:
        lm = "2"
    else:
        lm = None
    rs = "0"
    if obj.is_down or obj.is_up:
        rs = "1"
    if obj.ele_status:
        sm = "1"
        om = "0"
    elif obj.ele_status == 0:
        sm = "0"
        om = "1"
    else:
        sm = None
        om = None
    if obj.is_there_anyone:
        ps = "1"
    elif obj.is_there_anyone == 0:
        ps = "0"
    else:
        ps = None
    cp = obj.get_real_floor()
    t = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    data = {"f": f, "u": u, "d": d, "lm": lm, "rs": rs, "sm": sm, "om": om, "ps": ps, "cp": cp, "t": t}

    # # now = datetime.datetime.now()
    # # today = datetime.datetime(year=now.year, month=now.month, day=now.day)
    #
    # es = ElevatorStatus.objects.filter_active(o=o, create_time__gte=today).first()
    # # if not es:
    # #     es = ElevatorStatus()
    # # es.u = u
    # # es.d = d
    # # es.lm = lm
    # # es.rs = rs
    # # es.f = f
    # # es.om = om
    # # es.sm = sm
    # # es.ps = ps
    # # es.cp = cp
    # # es.o = o
    # # es.t = t
    # # if e:
    # #     es.e = e
    # es.save()
    ElevatorStatus.objects.update_or_create(o=o, defaults=data)
    from users.models import SystemLog, LogRefresh
    lr = LogRefresh.objects.filter_active(service_id=0).first()
    if lr and lr.refresh:
        data['o'] = o
        d = json.dumps(data)
        text = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "入库manufacturer_elevatorstatus表" + d
        SystemLog.objects.create(create_by=u"老朱", log=text, log_type=2)
    # try:
    #     logger.info(u"这是老朱的信息转化后的内容")
    #     logger.info(json.dumps(data))
    # except:
    #     pass
    print "elevator_status has been created or updated"


def status_update(b, b2, ac, floor, run_times):
    smg = StatusMsg.objects.filter_active(authority_code=ac).order_by("-id").first()
    authority_code = AuthorityCode.objects.filter(id=ac).first()
    if not smg:
        smg = StatusMsg()
        logger.info(u"新创建了status")
    b = b.lstrip('0b').zfill(8)
    b2 = b2.lstrip('0b').zfill(8)
    if b[-1] == '1':
        smg.is_stopped = 1     # 如果传过来的是停止的信号，is_stop 存为1 认为已经停止 但运行状态 is_up is_down 不做
        if authority_code.start_work_time:
            d_time = int(time.time()) - authority_code.start_work_time         # 电梯下线时 认为电梯停止 和 电梯停止时 取运行时间
            authority_code.up_time += d_time
        authority_code.start_work_time = 0
    elif b[-2] == '1':             # 变化 用来记录停止之前的状态，以计算钢丝绳折弯次数
        if smg.is_down == 1:
            authority_code.bend_times += 1
        if smg.is_stopped == 1:   # 如果上次状态是停止的 现在是开始的 那么运行时间开始计时
            authority_code.start_work_time = int(time.time())
        smg.is_up = 1
        smg.is_down = 0
        smg.is_stopped = 0
    elif b[-3] == '1':
        if smg.is_up == 1:
            authority_code.bend_times += 1
        if smg.is_stopped == 1:
            authority_code.start_work_time = int(time.time())
        smg.is_up = 0
        smg.is_down = 1
        smg.is_stopped = 0
    else:
        smg.is_stopped = 0

    if b[-4] == '1':
        smg.ele_status = 1
    else:
        smg.ele_status = 0
    if b[-5] == '1':
        smg.is_there_anyone = 1
    else:
        smg.is_there_anyone = 0
    if b[-6] == '1':
        smg.is_overhauling = 1
    else:
        smg.is_overhauling = 0

    if b2[-1] == '1':
        smg.is_closed = 1
        # if smg.is_closed == 0:
    else:
        smg.is_closed = 0
        authority_code.open_times += 1
    if b2[-2] == '1':
        smg.base_station_is_closed = 1
    else:
        smg.base_station_is_closed = 0
    if b2[-3] == '1':
        smg.upper_limit = 1
    else:
        smg.upper_limit = 0
    if b2[-4] == '1':
        smg.lower_limit = 1
    else:
        smg.lower_limit = 0
    if b2[-5] == '1':
        smg.upper_level = 1
    else:
        smg.upper_level = 0
    if b2[-6] == '1':
        smg.lower_level = 1
    else:
        smg.lower_level = 0
    if b2[-7] == '1':
        smg.body_induction = 1
    else:
        smg.body_induction = 0
    if b2[-8] == '1':
        smg.called = 1
    else:
        smg.called = 0
    authority_code.run_times = run_times
    authority_code.save()
    # authority_code.save(update_fields=['run_times', 'up_time', 'open_times', 'bend_times'])
    smg.floor = floor
    smg.authority_code = authority_code
    smg.save()
    elevator_status.delay(smg.id)
    from users.models import SystemLog, LogRefresh
    lr = LogRefresh.objects.filter_active(service_id=0).first()
    if lr and lr.refresh:
        d = json.dumps(smg.to_json())
        text = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "入库manufacturer_statusmsg表" + d
        SystemLog.objects.create(create_by=u"老朱", log=text, log_type=2)
    # try:
    #     logger.info(u"这是接收到老朱的状态信息")
    #     logger.info(json.dumps(smg.to_json()))
    # except:
    #     pass

    try:
        print "try to create or update elevator smg"
        create_elevator_status(smg)
    except Exception as e:
        print e


def get_floor(b):
    """ 电梯楼层修改为从0开始，此方法暂时不用"""
    if int(b, 2) < 128:
        return str(int(b, 2))
    else:
        f = b[3:]
        f = "-" + str(f)
        return f


def alarm_create(b, b2, authority_code):
    five_min_ago = datetime.datetime.now() - datetime.timedelta(minutes=5)
    alarm = AlarmMsg.objects.filter_active(authority_code=authority_code, update_time__gte=five_min_ago).order_by("-id").first()
    if not alarm:
        alarm = AlarmMsg()
        alarm.authority_code = authority_code
    b = b.lstrip('0b').zfill(8)
    b2 = b2.lstrip('0b').zfill(8)
    l = []
    if b[-1] == '1':
        alarm.is_alarm = 1
        l.append('1')
    if b[-2] == '1':
        alarm.is_trapped = 1
        l.append('2')
    if b[-3] == '1':
        alarm.stop_abnormal = 1
        l.append('3')
    if b[-4] == '1':
        alarm.circuit_break = 1
        l.append('4')
    if b[-5] == '1':
        alarm.is_top = 1
        l.append('5')
    if b[-6] == '1':
        alarm.is_bottom = 1
        l.append('6')
    if b[-7] == '1':
        alarm.go_with_open = 1
        l.append('7')
    if b2[-1] == '1':
        alarm.base_station_missed = 1
    if b2[-2] == '1':
        alarm.accidental_movement = 1
    if b2[-3] == '1':
        alarm.flat_fault = 1
    alarm.save()

    f = authority_code.manufacturer_code_elevator
    e = authority_code.elevator_code
    o = authority_code.device_code_elevator
    s = 'e'
    a = ",".join(l)

    ef = ElevatorFault.objects.filter_active(alarm_id=alarm.id).order_by("-id").first()
    if not ef:
        ef = ElevatorFault()
        ef.t = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        ef.sn = ef.t + str(datetime.datetime.now()).split(".")[1]
        ef.alarm_id = alarm.id
    ef.f = f
    ef.e = e
    ef.o = o
    ef.s = s
    ef.a = a
    ef.save()

    elevator_alarm.delay(alarm.id)


def data_escape(data, encapsulate=False):
    if not encapsulate:
        # 将接收到的数据去除转义
        pass
    else:
        # 将待发送的包转义
        pass














